﻿#include <list>
#include <CXXLOBJECT.HPP>
#include <SMART_PTR.HPP>
#include <GATE.HPP>
using namespace CxxlMan;

// cxxlObject::ptrown 變成此值時，將會被刪除
//#define KILLING NULL+1

class YanLuoWang
{
  std::list<cxxlObject*> cxxlObject_Lists; // 保存要 ReSet_toFind() 的物件
  CriticalSec csObject;
public:
  YanLuoWang(){}          // Constructor
  virtual ~YanLuoWang(){} // Destructor

  void Trial(cxxlObject *Obj)
  {
    // CriticalSecHandle CS(csObject);
    csObject.Enter();
    Obj->YanLuoWang_ChkIn();
    bool isKill = Obj->Trial();
    ReSet_toFind();
    if(isKill)
    {
      Obj->ClearHost();
      delete Obj;
    }
    else
      Obj->YanLuoWang_ChkOut();
    csObject.Leave();
  }

  void cxxlFASTCALL push(cxxlObject *Obj)
  {
    cxxlObject_Lists.push_front(Obj);
  }

  void cxxlFASTCALL ReSet_toFind()
  {
    while (!cxxlObject_Lists.empty())
    {
      cxxlObject *Obj = cxxlObject_Lists.back();
      cxxlObject_Lists.pop_back();
      Obj->ReSet_toFind();
    }
  }
}_YanLuoWang;


/*************************************
** Spirit_Urgent 的實作
*************************************/

class CXXL_DLLEXPORT SpiritUrgent:public ISpirit
{
  void cxxlFASTCALL ToDelete(cxxlObject *Obj) const
  {
    cxxlObjectUnLock(Obj);
    _YanLuoWang.Trial(Obj);
  }

  void cxxlFASTCALL ObjOver() const
  {
  }

  ISpirit *cxxlFASTCALL GetSpirit() const
  {
    return (SpiritUrgent *)this;
  }

public:
  SpiritUrgent()           // Constructor
  {
  }
  virtual ~SpiritUrgent()    // Destructor
  {
  }

  void operator delete(void *O,size_t s)
  {

  }


}_SpiritUrgent;

CXXL_DLLEXPORT ISpirit *CxxlMan::Spirit_Urgent = &_SpiritUrgent;


/*************************************
** Spirit_Easy 的實作
*************************************/

class Schedule
{
  CriticalSec csObject;
  Gate m_Gate;
  std::list<cxxlObject*> cxxlObject_Lists;
public:
  Schedule(); // Constructor

  virtual ~Schedule() // Destructor
  {
  }

  
  void cxxlFASTCALL pushf(cxxlObject *Obj)
  {
    csObject.Enter();
    cxxlObject_Lists.push_front(Obj);
    m_Gate.Signal();
    csObject.Leave();
  }

  void cxxlFASTCALL pushb(cxxlObject *Obj)
  {
    csObject.Enter();
    cxxlObject_Lists.push_back(Obj);
    m_Gate.Signal();
    csObject.Leave();
  }

  void cxxlFASTCALL Proc()
  {
    while(true)
    {
      m_Gate.Wait();

      while(true)
      {
        cxxlObject *Obj;

        csObject.Enter();

        if(!cxxlObject_Lists.empty())
        {
          Obj = cxxlObject_Lists.back();
          cxxlObject_Lists.pop_back();
        }
        else
        {
          csObject.Leave();
          break;
        }

        csObject.Leave();

        _YanLuoWang.Trial(Obj);
      }
    }
  }

}ScheduleObj;

#if (SysSelect == _WIN32_CxxlMan)

#include <windows.h>
#include <process.h>    /* _beginthread, _endthread */

// 新執行緒的進入點，ScheduleObj::Proc() 在這個執行緒工作
static unsigned __stdcall ThreadMain(void *)
{
  ScheduleObj.Proc();

  return 0;
}

// Constructor
Schedule::Schedule()
{
  HANDLE hThreads;
  unsigned threadId;

  hThreads = (HANDLE)_beginthreadex(
               NULL,                 /* Thread security */
               0,                    /* Thread stack size */
               ThreadMain,           /* Thread starting address */
               NULL,                 /* Thread start argument */
               0,                    /* Runs immediately after creation */
               &threadId);
  CloseHandle(hThreads);
}

#elif (SysSelect == _LINUX_CxxlMan)

#include <pthread.h>

// 新執行緒的進入點，ScheduleObj::Proc() 在這個執行緒工作
static void *cxxlFASTCALL ThreadMain(void *)
{
  ScheduleObj.Proc();

  return NULL;
}

// Constructor
Schedule::Schedule()
{
  pthread_t ThreadID;

  pthread_create( &ThreadID, pthread_attr_default, ThreadMain,(void *)NULL)
}


#else
  #error 尚未支援此作業系統
#endif



class CXXL_DLLEXPORT SpiritEasy:public ISpirit
{
  void cxxlFASTCALL ToDelete(cxxlObject *Obj) const
  {
    bool F;

    if(GetFlag(Obj) == false)
    {
      SetFlag(Obj,true);
      F = true;
    }
    else
      F = false;

    cxxlObjectUnLock(Obj);
    if(F)
      ScheduleObj.pushb(Obj); // 一般物件會先被取出
  }

  void cxxlFASTCALL ObjOver() const
  {
  }

  ISpirit *cxxlFASTCALL GetSpirit() const
  {
    return (SpiritEasy *)this;
  }

public:
  SpiritEasy(){}           // Constructor
  virtual ~SpiritEasy()    // Destructor
  {
  }

  void operator delete(void *O,size_t s)
  {

  }


}_SpiritEasy;

CXXL_DLLEXPORT ISpirit *CxxlMan::Spirit_Easy = &_SpiritEasy;


/*************************************
** Spirit_DllFileContext 的實作
** 只給 centralizedmgr.cpp 中的 DllFileContext 使用
*************************************/

class CXXL_DLLEXPORT SpiritDllFileContext:public ISpirit
{
  void cxxlFASTCALL ToDelete(cxxlObject *Obj) const
  {
    bool F;

    if(GetFlag(Obj) == false)
    {
      SetFlag(Obj,true);
      F = true;
    }
    else
      F = false;

    cxxlObjectUnLock(Obj);
    if(F)
      ScheduleObj.pushf(Obj); // 比 DllFileContext 所取得的物件要晚被取出
  }

  void cxxlFASTCALL ObjOver() const
  {
  }

  ISpirit *cxxlFASTCALL GetSpirit() const
  {
    return (SpiritDllFileContext *)this;
  }

public:
  SpiritDllFileContext(){}           // Constructor
  virtual ~SpiritDllFileContext()    // Destructor
  {
  }

  void operator delete(void *O,size_t s)
  {

  }


}_SpiritDllFileContext;

CXXL_DLLEXPORT ISpirit *Spirit_DllFileContext = &_SpiritDllFileContext;



/*********************************************
** class cxxlObject 程式碼
*********************************************/

// 加入指定的智彗指標到串列中
void cxxlFASTCALL cxxlObject::AttachPtr(Smart_Ptr_Base *Ptr)
{
  csObject.Enter();

  if(ptrown != NULL)
  {
    Ptr->Prev = NULL;
    Ptr->Next = ptrown;
    ptrown->Prev = Ptr;
    ptrown = Ptr;
  }
  else
  {
    Ptr->Prev = NULL;
    Ptr->Next = NULL;
    False_isRoot();

    ptrown = Ptr;
  }

  csObject.Leave();
}

// 從串列中移除指定的智彗指標
void cxxlFASTCALL cxxlObject::DetachPtr(Smart_Ptr_Base *Ptr)
{
    csObject.Enter();

    if(Ptr->Prev != NULL)
      Ptr->Prev->Next = Ptr->Next;
    else
      ptrown = Ptr->Next;

    if(Ptr->Next != NULL)
      Ptr->Next->Prev = Ptr->Prev;

    // csObject.Leave(); // 改交由 Spirit 處理

    Spirit->ToDelete(this);
}


void cxxlFASTCALL cxxlObject::ClearHost() 
{
  while(ptrown)
  {
    ptrown->ClearObjToNULL();
    ptrown = ptrown->Next;
  }
}

bool cxxlFASTCALL cxxlObject::Trial()
{
  CriticalSecHandle CS(csObject);

  if(ptrown == NULL) // 無持有者了
    return true;

  toFind = &CxxlMan::cxxlObject::Finded;  // 設為已找過的狀態
  _YanLuoWang.push(this);  // 保存，要被 ReSet_toFind()

  cxxlObject *host;
  bool R; // 找不到 rootObject 回覆 true

  Smart_Ptr_Base *p = ptrown;
  do
  {
    host = p->m_Host;
    R = (host->*(host->toFind))();

    if(R == false) // 有找到 rootObject 或還有要放棄持有的處理
      break;
    p = p->Next;

  }while(p);

  if(R == false)
    Spirit_Flag = false;  // 可再被放入待刪佇列

  return R;
}

void cxxlFASTCALL cxxlObject::ReSet_toFind()
{
  toFind = &CxxlMan::cxxlObject::Find_rootObject; // 恢復為可再被尋找的狀態
}


bool cxxlFASTCALL cxxlObject::Find_rootObject()
{
  CriticalSecHandle CS(csObject);

  if(isRoot)  // 本身是 rootObject,或未放入過 Smart_Ptr
    return false;

  if(ptrown == NULL) 
    return false;  // 告知我也要處理待確認的 cxxlObject

  toFind = &CxxlMan::cxxlObject::Finded;  // 設為已找過的狀態
  _YanLuoWang.push(this);  // 保存，要被 ReSet_toFind()

  cxxlObject *host;
  bool R; // 找不到 rootObject 回覆 true

  Smart_Ptr_Base *p = ptrown;
  do
  {
    host = p->m_Host;
    R = (host->*(host->toFind))(); 

    if(R == false) // 有找到 rootObject 或還有要放棄持有的處理
      break;
    p = p->Next;

  }while(p);

  return R;
}

bool cxxlFASTCALL cxxlObject::Finded()
{
  return true;
}

void cxxlFASTCALL cxxlObject::False_isRoot()
{
  isRoot = false;
}


/******************************************
** rootObject 實作
******************************************/

class CXXL_DLLEXPORT SpiritNull:public ISpirit
{
  void cxxlFASTCALL ToDelete(cxxlObject *Obj) const
  {
  }

  void cxxlFASTCALL ObjOver() const
  {
  }

  ISpirit *cxxlFASTCALL GetSpirit() const
  {
    return (SpiritNull *)this;
  }

public:
  SpiritNull(){}           // Constructor
  virtual ~SpiritNull()    // Destructor
  {
  }

  void operator delete(void *O,size_t s)
  {

  }

}_SpiritNull;


class CXXL_DLLEXPORT ImpRootObject:public cxxlObject
{
public:
  ImpRootObject()
    :cxxlObject(&_SpiritNull)
  {}

  ~ImpRootObject(){}

  // 避免被放入 Smart_Ptr 變成不是 rootObject
  void cxxlFASTCALL False_isRoot()
  {
  }

}_rootObject;

CXXL_DLLEXPORT cxxlObject *CxxlMan::rootObject = &_rootObject;

/******************************************
** class Smart_Ptr_Base 的程式碼
******************************************/

// Constructor
Smart_Ptr_Base::Smart_Ptr_Base(cxxlObject *Obj,cxxlObject *Host)
{
  m_Host = Host;
  Attach(Obj);
}


void cxxlFASTCALL Smart_Ptr_Base::Attach(cxxlObject *Obj)
{
  if(Obj != NULL)
    Obj->AttachPtr(this);
}

void cxxlFASTCALL Smart_Ptr_Base::Release(cxxlObject *Obj)
{
  if(Obj != NULL)
  {
    Obj->DetachPtr(this);
  }
}

